package com.tjbklx1.redis.chap02;

import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;

import redis.clients.jedis.Jedis;

/**
 * 案例2.1 保存登录cookie
 * 
 * @date 2018年9月7日
 */
public class App21 {

	public static void main(String[] args) throws InterruptedException {
		Jedis conn = new Jedis("localhost");
		conn.select(0);

		new App21().testLoginCookies(conn);

		conn.close();
	}

	public void testLoginCookies(Jedis conn) throws InterruptedException {
		System.out.println("\n----- testLoginCookies -----");
		
		//token
		String token = UUID.randomUUID().toString();

		updateToken(conn, token, "username", "itemX");
		System.out.println("We just logged-in/updated token: " + token);
		System.out.println("For user: 'username'");
		System.out.println();

		System.out.println("What username do we get when we look-up that token?");
		String r = checkToken(conn, token);
		System.out.println(r);
		System.out.println();
		assert r != null;

		System.out.println("Let's drop the maximum number of cookies to 0 to clean them out");
		System.out.println("We will start a thread to do the cleaning, while we stop it later");

		CleanSessionsThread thread = new CleanSessionsThread(10*60*1000);
		thread.start();
		Thread.sleep(1000);
		thread.quit();
		Thread.sleep(2000);
		if (thread.isAlive()) {
			throw new RuntimeException("The clean sessions thread is still alive?!?");
		}

		long s = conn.hlen("login:");
		System.out.println("The current number of sessions still available is: " + s);
		assert s == 0;
	}

	/**
	 * 更新token
	 * @param conn
	 * @param token
	 * @param user
	 * @param item
	 * @date 2018年9月7日
	 */
	public void updateToken(Jedis conn, String token, String user, String item) {
		//当前时间
		long timestamp = System.currentTimeMillis() / 1000;
		//保存 登录token
		conn.hset("login:", token, user);
		// 保存登录时间
		conn.zadd("recent:", timestamp, token);
		if (item != null) {
			//保存看过的商品
			conn.zadd("viewed:" + token, timestamp, item);
			//删除25之前的商品
			conn.zremrangeByRank("viewed:" + token, 0, -26);
			//更新计数器
			conn.zincrby("viewed:", -1, item);
		}
	}

	/**
	 * 检测登录的token
	 * @param conn
	 * @param token
	 * @return
	 * @date 2018年9月7日
	 */
	public String checkToken(Jedis conn, String token) {
		return conn.hget("login:", token);
	}

	/**
	 * 清除session
	 * @date 2018年9月7日
	 */
	public class CleanSessionsThread extends Thread {
		private Jedis conn;
		private int limit;
		private boolean quit;

		public CleanSessionsThread(int limit) {
			this.conn = new Jedis("localhost");
			this.conn.select(0);
			this.limit = limit;
		}

		public void quit() {
			quit = true;
		}

		public void run() {
			while (!quit) {
				long size = conn.zcard("recent:");
				//小于限制的大小 休息1秒
				if (size <= limit) {
					try {
						sleep(1000);
					} catch (InterruptedException ie) {
						Thread.currentThread().interrupt();
					}
					continue;
				}

				//???
				long endIndex = Math.min(size - limit, 100);
				Set<String> tokenSet = conn.zrange("recent:", 0, endIndex - 1);
				String[] tokens = tokenSet.toArray(new String[tokenSet.size()]);

				ArrayList<String> sessionKeys = new ArrayList<String>();
				for (String token : tokens) {
					sessionKeys.add("viewed:" + token);
				}

				conn.del(sessionKeys.toArray(new String[sessionKeys.size()])); //删除登录的cookie
				conn.hdel("login:", tokens);//删除登录信息
				conn.zrem("recent:", tokens);//删除最近浏览的商品
			}
		}
	}
}
